// import type { IncomingMessage } from "http";
// import type { ClientHttp2Stream } from "http2";

// import { ClientHttp2Stream, IncomingMessage } from "../index";
import type { InvokeMethod } from "../client";
import type { GetOutputType } from "../command";
import type { HttpHandlerOptions } from "../http";
import type { SdkStream } from "../serde";
import type {
  NodeJsRuntimeStreamingBlobPayloadInputTypes,
  StreamingBlobPayloadInputTypes,
} from "../streaming-payload/streaming-blob-payload-input-types";
import type { StreamingBlobPayloadOutputTypes } from "../streaming-payload/streaming-blob-payload-output-types";
import type { NarrowedInvokeMethod } from "./client-method-transforms";
import type { Transform } from "./type-transform";

/**
 * @public
 *
 * Creates a type with a given client type that narrows payload blob output
 * types to SdkStream<IncomingMessage>.
 *
 * This can be used for clients with the NodeHttpHandler requestHandler,
 * the default in Node.js when not using HTTP2.
 *
 * Usage example:
 * ```typescript
 * const client = new YourClient({}) as NodeJsClient<YourClient>;
 * ```
 */
// export type NodeJsClient<ClientType extends object> = NarrowPayloadBlobTypes<
//   NodeJsRuntimeStreamingBlobPayloadInputTypes,
//   SdkStream<IncomingMessage>,
//   ClientType
// >;
/**
 * @public
 * Variant of NodeJsClient for node:http2.
 */
// export type NodeJsHttp2Client<ClientType extends object> = NarrowPayloadBlobTypes<
//   NodeJsRuntimeStreamingBlobPayloadInputTypes,
//   SdkStream<ClientHttp2Stream>,
//   ClientType
// >;

/**
 * @public
 *
 * Creates a type with a given client type that narrows payload blob output
 * types to SdkStream<ReadableStream>.
 *
 * This can be used for clients with the FetchHttpHandler requestHandler,
 * which is the default in browser environments.
 *
 * Usage example:
 * ```typescript
 * const client = new YourClient({}) as BrowserClient<YourClient>;
 * ```
 */
// export type BrowserClient<ClientType extends object> = NarrowPayloadBlobTypes<
//   BrowserRuntimeStreamingBlobPayloadInputTypes,
//   SdkStream<ReadableStream>,
//   ClientType
// >;
/**
 * @public
 *
 * Variant of BrowserClient for XMLHttpRequest.
 */
// export type BrowserXhrClient<ClientType extends object> = NarrowPayloadBlobTypes<
//   BrowserRuntimeStreamingBlobPayloadInputTypes,
//   SdkStream<ReadableStream | Blob>,
//   ClientType
// >;

/**
 * @public
 *
 * @deprecated use NarrowPayloadBlobTypes<I, O, ClientType>.
 *
 * Narrow a given Client's blob payload outputs to the given type T.
 */
export type NarrowPayloadBlobOutputType<T, ClientType extends object> = {
  [key in keyof ClientType]: [ClientType[key]] extends [
    InvokeMethod<infer FunctionInputTypes, infer FunctionOutputTypes>,
  ]
    ? NarrowedInvokeMethod<T, HttpHandlerOptions, FunctionInputTypes, FunctionOutputTypes>
    : ClientType[key];
} & {
  send<Command>(
    command: Command,
    options?: any
  ): Promise<Transform<GetOutputType<Command>, StreamingBlobPayloadOutputTypes | undefined, T>>;
};

/**
 * @public
 *
 * Narrow a Client's blob payload input and output types to I and O.
 */
export type NarrowPayloadBlobTypes<I, O, ClientType extends object> = {
  [key in keyof ClientType]: [ClientType[key]] extends [
    InvokeMethod<infer FunctionInputTypes, infer FunctionOutputTypes>,
  ]
    ? NarrowedInvokeMethod<
        O,
        HttpHandlerOptions,
        Transform<FunctionInputTypes, StreamingBlobPayloadInputTypes | undefined, I>,
        FunctionOutputTypes
      >
    : ClientType[key];
} & {
  send<Command>(
    command: Command,
    options?: any
  ): Promise<Transform<GetOutputType<Command>, StreamingBlobPayloadOutputTypes | undefined, O>>;
};
